﻿// -------------------------------------------------------------------------
//    @FileName         :    NFPackagePart.h
//    @Author           :    gaoyi
//    @Date             :    24-8-29
//    @Email            :    445267987@qq.com
//    @Module           :    NFPackagePart
//
// -------------------------------------------------------------------------

// --- 文件总结 ---------------------------------------------------------------
// `NFPackagePart` 是玩家背包部件类：
// - 管理玩家的所有背包页签（装备、材料、道具、称号、皮肤、宝石等）
// - 提供背包容量管理、物品增删改查、排序等功能
// - 管理玩家的货币（金钱）数据
// - 管理物品使用限制
// - 处理临时存储
// - 继承自 NFPart，是玩家数据的一个部件
// ---------------------------------------------------------------------------

#pragma once

#include <NFComm/NFShmStl/NFShmList.h>
#include <NFLogicCommon/NFLogicShmTypeDefines.h>
#include "NFPart.h"
#include "NFLogicCommon/BagPage/NFBagPage.h"
#include "NFLogicCommon/NFPackageDefine.h"

/**
 * @brief 玩家背包部件类
 * 管理玩家的所有背包页签、货币和物品使用限制
 */
class NFPackagePart : public NF_OBJECT_TEMPLATE_MACRO(NFPackagePart, EOT_LOGIC_PART_MIN_ID + PART_PACKAGE, NFPart)
public:
    /**
     * @brief 构造函数
     */
    NFPackagePart();

    /**
     * @brief 析构函数
     */
    ~NFPackagePart() override;

    /**
     * @brief 创建初始化
     * @return 0成功，非0失败
     */
    int CreateInit();
    
    /**
     * @brief 恢复初始化（从共享内存恢复）
     * @return 0成功，非0失败
     */
    int ResumeInit();

public:
    //******************part调用接口******************
    /**
     * @brief 所有部件初始化完成
     * @return
     */
    int OnInit() override { return 0; }

public:
    /**
     * @brief 从数据库中加载数据
     * @param data
     * @return
     */
    int LoadFromDB(const proto_ff::tbRoleDetail* pDBData) override;

    /**
     * @brief 从配置中初始化数据
     * @return
     */
    int InitConfig(proto_ff::tbRoleDetail* pDbData, const RoleOne& stRoleOne) override;

    /**
     * @brief 存储DB部件入口
     * @param proto
     * @return
     */
    int SaveDB(proto_ff::tbRoleDetail* pDBData) override;

    /**
    * @brief 注册后的初始�?
    * @return
    */
    int OnRegister() override;

    /**
     * @brief 登陆入口
     * @return
     */
    int OnLogin() override { return 0; }

    /**
     * @brief 登出入口
     * @return
     */
    int OnLogout() override { return 0; }

    /**
     * @brief 掉线入口
     * @return
     */
    int OnDisconnect() override { return 0; }

    /**
     * @brief 重连入口
     * @return
     */
    int OnReconnect() override { return 0; }

    ////////////////////////////////// 每日零点 每周一零点 刷新接口 ///////////////////////////////////
    /**
     * @brief 每日零点 刷新接口
     * @return
     */
    int DayTick() override { return 0; }

    /**
     * @brief 每日零点 刷新接口
     * @return
     */
    int WeekTick() override { return 0; }

    /**
     * @brief 每月刷新接口
     * @return
     */
    int MonthTick() override { return 0; };

public:
    /**
     * @brief update
     */
    int LogicTick() override { return 0; }
public:
    int MakePlayerDataCS(proto_ff::Proto_CSGetRoleRsp* pCSGetRoleRsp) override;
    int MakeCityPlayerData(proto_ff::CityRoleInfo* pGCCityRoleInfo) override;
    int SaveRoleSimpleInfo(proto_ff::Proto_RoleSimpleInfo* pDbData) override;
public:
    /**
     * @brief 根据页签类型获取相应的页签对象
     * @param iPageType 页签类型，用于区分不同的页签
     * @return 返回背包页签指针，如果找不到匹配类型的页签，返回 nullptr
     */
    NFBagPage* GetPageByType(int iPageType);
    
    /**
     * @brief 根据页签类型获取相应的页签对象（const版本）
     * @param iPageType 页签类型
     * @return 返回背包页签指针（const）
     */
    const NFBagPage* GetPageByType(int iPageType) const;

    /**
     * @brief 检查给定物品ID的背包是否已满
     * @param iItemID 物品ID，用于识别需要检查的物品类型
     * @return true背包已满，false背包未满
     */
    bool IsFull(uint32_t iItemID);

    /**
     * @brief 整理指定的背包页签（排序）
     * @param iPage 要整理的背包页签索引
     * @return 返回整理后的背包页签指针，如果页签索引无效或操作失败，返回nullptr
     */
    NFBagPage* Arrage(int iPage);

public:
    /**
     * @brief 获取指定背包页签的容量
     * @param iBagType 背包页签类型
     * @return 页签容量
     */
    int GetCapacity(int iBagType) const;
    
    /**
     * @brief 获取指定背包页签的空格子数量
     * @param iBagType 背包页签类型
     * @return 空格子数量
     */
    int GetEmptyGridNum(int iBagType) const;

    /**
     * @brief 从指定背包页签获取指定格子的物品
     * @param iBagType 背包页签类型
     * @param iGridIndex 格子索引
     * @param pItemOut 输出物品
     * @return 0成功，非0失败
     */
    int GetItem(int iBagType, int iGridIndex, NFGridItem* pItemOut) const;
    
    /**
     * @brief 从指定背包页签获取所有物品
     * @param iBagType 背包页签类型
     * @param vecItem 输出物品列表
     * @return 0成功，非0失败
     */
    int GetItem(int iBagType, std::vector<NFGridItem>& vecItem) const;
    
    /**
     * @brief 获取指定背包页签中指定物品的数量
     * @param iBagType 背包页签类型
     * @param iItemId 物品ID
     * @return 物品数量
     */
    int GetItemNum(int iBagType, int iItemId) const;
    
    /**
     * @brief 根据UUID从指定背包页签获取物品
     * @param iBagType 背包页签类型
     * @param ullUUID 物品UUID
     * @param pItemOut 输出物品
     * @return 0成功，非0失败
     */
    int GetItemByUUID(int iBagType, uint64_t ullUUID, NFGridItem* pItemOut) const;
    
    /**
     * @brief 根据物品ID从指定背包页签获取物品
     * @param iBagType 背包页签类型
     * @param iItemID 物品ID
     * @param pItemOut 输出物品
     * @return 0成功，非0失败
     */
    int GetItemByItemId(int iBagType, int iItemID, NFGridItem* pItemOut) const;
    
    /**
     * @brief 扩展指定背包页签的容量
     * @param iBagType 背包页签类型
     * @param iIncreaseCapacityNum 要增加的容量数
     * @return 0成功，非0失败
     */
    int ExpandCapacity(int iBagType, int iIncreaseCapacityNum);
    
    /**
     * @brief 缩减指定背包页签的容量
     * @param iBagType 背包页签类型
     * @param iDecreaseCapacityNum 要减少的容量数
     * @return 0成功，非0失败
     */
    int ShrinkCapacity(int iBagType, int iDecreaseCapacityNum);

    /**
     * @brief 根据UUID从指定背包页签获取物品（const版本）
     * @param iBagType 背包页签类型
     * @param ullUUID 物品UUID
     * @return 物品指针（const），未找到返回nullptr
     */
    const NFGridItem* GetItemByUUID(int iBagType, uint64_t ullUUID) const;
    
    /**
     * @brief 根据UUID从指定背包页签获取物品
     * @param iBagType 背包页签类型
     * @param ullUUID 物品UUID
     * @return 物品指针，未找到返回nullptr
     */
    NFGridItem* GetItemByUUID(int iBagType, uint64_t ullUUID);

private:
    /** @brief 是否已初始化 */
    bool m_bIsInited;
private:
    /** @brief 装备背包页签 */
    NFBagPageImpl<MAX_GRID_OF_BAG> m_stPageEquip;
    /** @brief 材料背包页签 */
    NFBagPageImpl<MAX_GRID_OF_BAG> m_stPageMatrial;
    /** @brief 道具背包页签 */
    NFBagPageImpl<MAX_GRID_OF_BAG> m_stPageProp;
    /** @brief 称号背包页签 */
    NFBagPageImpl<MAX_GRID_OF_TITLE> m_stPageTitle;
    /** @brief 皮肤背包页签 */
    NFBagPageImpl<MAX_GRID_OF_SKIN> m_stPageSkin;
    /** @brief 宝石背包页签 */
    NFBagPageImpl<MAX_GRID_OF_GEM> m_stPageGem;
    /** @brief 伙伴装备背包页签 */
    NFBagPageImpl<MAX_GRID_OF_PARTNER_EQUIP> m_stPagePartnerEquip;
    /** @brief 伙伴装备石背包页签 */
    NFBagPageImpl<MAX_GRID_OF_PARTNER_EQUIP_STONE> m_stPagePartnerEquipStone;
    /** @brief 伙伴令牌背包页签 */
    NFBagPageImpl<MAX_GRID_OF_PARTNER_TOKEN> m_stPagePartnerToken;
    /** @brief Buff装备背包页签 */
    NFBagPageImpl<MAX_GRID_OF_BUFF_EQUIP> m_stPageBuffEquip;
    /** @brief 临时存储页签 */
    NFBagPageImpl<MAX_TEMP_STORAGE_SIZE> m_stPageTempStorage;
    /** @brief 已穿戴物品页签 */
    NFBagPageImpl<MAX_DRESSED_ITEM> m_stPageDressedItems;

public:
    /**
     * @brief 获取金钱对象
     * @param iItemID 金钱类型ID
     * @return 金钱对象指针，未找到返回nullptr
     */
    Money* GetMoney(int iItemID);
    
    /**
     * @brief 获取金钱数量
     * @param iItemID 金钱类型ID
     * @return 金钱数量
     */
    uint64_t GetMoneyNumber(int iItemID);
    
    /**
     * @brief 设置金钱数量
     * @param iItemID 金钱类型ID
     * @param iNum 金钱数量
     * @return 0成功，非0失败
     */
    int SetMoneyNumber(int iItemID, int iNum);

private:
    /** @brief 金钱映射表 */
    NFShmHashMap<int, Money, MAX_MONEY_TYPE_NUM> m_astMoneyMap;

public:
    /**
     * @brief 检查物品使用限制是否已满
     * @return true已满，false未满
     */
    bool IsUseLimiteFull() { return m_astItemUseLimit.size() >= m_astItemUseLimit.max_size(); }
    
    /**
     * @brief 获取物品使用限制
     * @param iItemId 物品ID
     * @return 物品使用限制指针，未找到返回nullptr
     */
    ItemUseLimite* GetItemUseLimite(int iItemId);
    
    /**
     * @brief 检查物品使用限制
     * @param iItemId 物品ID
     * @param iNum 使用数量
     * @return 0成功，非0失败
     */
    int CheckUseLimite(int iItemId, int iNum);
    
    /**
     * @brief 使用物品（更新使用限制）
     * @param iItemId 物品ID
     * @param iNum 使用数量
     * @return 0成功，非0失败
     */
    int OnUse(int iItemId, int iNum);
    
    /**
     * @brief 检查临时存储是否有物品
     * @return true有物品，false无物品
     */
    bool IsTempStorageHasItem();
private:
    /** @brief 物品使用限制映射表 */
    NFShmHashMap<int, ItemUseLimite, MAX_ITEM_USE_LIMIT> m_astItemUseLimit;
};
